#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
using namespace cv;
using namespace std;

vector<Rect> facedetect( Mat &img , CascadeClassifier& cascade )
{
    vector<Rect> tmp_faces;
    Mat gray;
    cvtColor( img , gray , COLOR_BGR2GRAY );
    cascade.detectMultiScale( gray, tmp_faces,
                                1.1, 3, 0 
                                //|CASCADE_FIND_BIGGEST_OBJECT
                                //|CASCADE_DO_ROUGH_SEARCH
                                |CASCADE_SCALE_IMAGE,
                                Size(30, 30) );
    return tmp_faces;
}

void drawfaceandeye( Mat &img , vector<Rect> &temp_faces , CascadeClassifier& nestedCascade )
{
    for ( size_t i = 0; i < temp_faces.size(); i++ )
    {
        Rect r = temp_faces[i];
        vector<Rect> nestedObjects;
        Point center;
        int radius;
        Mat smallImgROI;

        rectangle( img, Point(cvRound(r.x*1), cvRound(r.y*1)),
                    Point(cvRound((r.x + r.width-1)*1), cvRound((r.y + r.height-1)*1)),
                    Scalar(255,128,0), 3, 8, 0);
        
        smallImgROI = img( r );
        nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
                                            1.1, 2, 0
                                            //|CASCADE_FIND_BIGGEST_OBJECT
                                            //|CASCADE_DO_ROUGH_SEARCH
                                            //|CASCADE_DO_CANNY_PRUNING
                                            |CASCADE_SCALE_IMAGE,
                                            Size(30, 30) );
         for ( size_t j = 0; j < nestedObjects.size(); j++ )
        {
            Rect nr = nestedObjects[j];
            center.x = cvRound((r.x + nr.x + nr.width*0.5)*1);
            center.y = cvRound((r.y + nr.y + nr.height*0.5)*1);
            radius = cvRound((nr.width + nr.height)*0.25*1);
            circle( img, center, radius, Scalar(0,128,255), 3, 8, 0 );
        }             
    }
}
/*
void traingdata( const string &filepath , vector<Rect> &temp_faces ,vector<Rect> &temp_lables )
{
    Mat temp_image ;
    vector<Rect> temp_face;
    int fd = open( filepath , O_RDONLY )
    
    if( -1 != fd )
    {
        perror( "wrong file path!\n" );
    }
     //加入互斥量进行保护
    for( uint16_t i = 0 ; i < 3; i++ )
    {
        //facedetect
        string imgpath = filepath +'/'+ file name;
        temp_image = imread( imgpath );
        temp_face = facedetect( temp_image , cascade );
        if( temp_face.size() != 0 )
        {
            temp_faces.append(temp_face);
            temp_lables.append(name);
        }
    }
    //退出互斥量保护

}
*/


int main(int argc, char** argv )
{
	
    if ( argc != 2 )
    {
        printf("usage: DisplayImage.out <Image_Path>\n");
        return -1;
    }
    Mat image ;
    VideoCapture capture;

    /*if(!capture.open(0))
    {
        cout << "Capture from camera 0" <<  0 << " didn't work" << endl;
        return 1;
    }
    if( capture.isOpened() )
    {
        cout << "camera open sucess!\n"<< endl;
    }*/
    image = imread( argv[1], 1 );
    if ( !image.data )
    {
        printf("No image data \n");
        return -1;
    }
    printf("read picture sucess!\n");
    
    /*加载特征模型*/
    CascadeClassifier cascade , nested_cascade;
    cascade.load("data/haarcascades/haarcascade_frontalface_alt.xml");
    nested_cascade.load("data/haarcascades/haarcascade_eye_tree_eyeglasses.xml");

    /*预处理*/
    vector<Mat> imgs;
    vector<int> lables;
    imgs.push_back(imread("traindata/0/0.jpg", IMREAD_GRAYSCALE)); lables.push_back(0);
    imgs.push_back(imread("traindata/0/1.jpg", IMREAD_GRAYSCALE)); lables.push_back(0);
    imgs.push_back(imread("traindata/0/2.jpg", IMREAD_GRAYSCALE)); lables.push_back(0);


    /*学习生成训练数据*/
    Ptr<FaceRecognizer> LBHPmode = face::LBPHFaceRecognizer::create();
    LBHPmode->train( imgs , lables );
    LBHPmode->save( "LBPHmode.xml" );
   
    double t = (double)getTickCount();
    vector<Rect> faces;
    faces = facedetect( image , cascade );
    t = (double)getTickCount() - t;
    printf( "detection time = %g ms\n", t*1000/getTickFrequency());
    printf(" get %d faces!\n " , faces.size());
    drawfaceandeye( image , faces, nested_cascade );
  
    imwrite( "ouputface.jpg" , image );
    printf( "out put draw picture!\n" );

    int lable = LBHPmode->predict( image );
    printf( "reconize lable is %d\n" , lable );

    return 0;
}
